package com.greensam.pixelengine.utils;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.greensam.pixelengine.constant.BaseConstant;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

/**
 * @author Macro_Ray
 * @since 2025/6/21 1:37
 */
public class DateTimeFormatterUtils {

    private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern(BaseConstant.DATETIME_PATTERN);
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern(BaseConstant.DATE_PATTERN);
    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern(BaseConstant.TIME_PATTERN);

    /**
     * LocalDateTime序列化和反序列化
     *
     * @author Macro_Ray
     * @since 2025/6/21
     */
    public SimpleModule localDateTime() {
        SimpleModule module = new SimpleModule();

        // LocalDateTime序列化器
        module.addSerializer(LocalDateTime.class, new JsonSerializer<LocalDateTime>() {
            @Override
            public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                if (value != null) {
                    gen.writeString(value.format(DATETIME_FORMATTER));
                } else {
                    gen.writeNull();
                }
            }
        });

        // LocalDateTime反序列化器
        module.addDeserializer(LocalDateTime.class, new JsonDeserializer<LocalDateTime>() {
            @Override
            public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
                String text = p.getValueAsString();
                if (text == null || text.isBlank()) return null;
                try {
                    return LocalDateTime.parse(text, DATETIME_FORMATTER);
                } catch (Exception e) {
                    throw new JsonProcessingException("Invalid LocalDateTime format: " + text, e) {
                    };
                }
            }
        });

        return module;
    }

    /**
     * LocalDate序列化和反序列化
     *
     * @author Macro_Ray
     * @since 2025/6/21
     */
    public SimpleModule localDate() {
        SimpleModule module = new SimpleModule();

        module.addSerializer(LocalDate.class, new JsonSerializer<LocalDate>() {
            @Override
            public void serialize(LocalDate value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                if (value != null) {
                    gen.writeString(value.format(DATE_FORMATTER));
                } else {
                    gen.writeNull();
                }
            }
        });

        module.addDeserializer(LocalDate.class, new JsonDeserializer<LocalDate>() {
            @Override
            public LocalDate deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
                String text = p.getValueAsString();
                if (text == null || text.isBlank()) return null;
                try {
                    return LocalDate.parse(text, DATE_FORMATTER);
                } catch (Exception e) {
                    throw new JsonProcessingException("Invalid LocalDate format: " + text, e) {
                    };
                }
            }
        });

        return module;
    }

    /**
     * LocalTime序列化和反序列化
     *
     * @author Macro_Ray
     * @since 2025/6/21
     */
    public SimpleModule localTime() {
        SimpleModule module = new SimpleModule();

        module.addSerializer(LocalTime.class, new JsonSerializer<LocalTime>() {
            @Override
            public void serialize(LocalTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                if (value != null) {
                    gen.writeString(value.format(TIME_FORMATTER));
                } else {
                    gen.writeNull();
                }
            }
        });

        module.addDeserializer(LocalTime.class, new JsonDeserializer<LocalTime>() {
            @Override
            public LocalTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
                String text = p.getValueAsString();
                if (text == null || text.isBlank()) return null;
                try {
                    return LocalTime.parse(text, TIME_FORMATTER);
                } catch (Exception e) {
                    throw new JsonProcessingException("Invalid LocalTime format: " + text, e) {
                    };
                }
            }
        });

        return module;
    }
}
